#include "mpoint.h"
#include "tools.h"
#include "map.h"
#include "gdi.h"

MPoint::~MPoint()
	{
	// TODO: ~CMPoint
	SAFE_DELETE(latlong);
	SAFE_DELETE(name);
	SAFE_DELETE(mBmp);
	}

MPoint::MPoint()
	: id(0)
	, x(0)
	, y(0)
	, latlong(NULL)
	, latitude(0)
	, longitude(0)
	, name(NULL)
	, mBmp(NULL)
	, bmpWidth(0)
	, bmpHeight(0)
	, mDrawMode(-1)
	, map(NULL)
	, mode(false)
	{
	}

MPoint::MPoint(int zoom, int offsetX, int offsetY)
	: MPoint()
	{
	SetOffset(zoom,offsetX,offsetY);
	}
    
/**
 * 
 * @param zoom: 级别
 * @param offsetX: zoom级别点的偏移量X
 * @param offsetY" zoom级别点的偏移量Y
 */
void MPoint::SetOffset(int zoom,int offsetX,int offsetY)
	{
    const TPoint* obj = mOffsetTable.Find(zoom);
    if (NULL == obj)
    {
        mOffsetTable.Insert(zoom, TPoint(offsetX,offsetY));
    }
    
    // 把当前点所有0-13级别的偏移量计算一次
    for (int i = zoom; i > MAP_ZOOM_MIN; i--)
    {
        int nzoom = i - 1;
        if (mOffsetTable.Find(nzoom) == NULL)
        {
            AdjustPointOffset(i,nzoom);
        }
    }
    
    for(int i = zoom; i < MAP_ZOOM_MAX; i++)
    {
        int nzoom = i + 1;
        if(mOffsetTable.Find(nzoom) == NULL)
        {
            AdjustPointOffset(i,nzoom);
        }
    }
	}

/**
 * 设置点的图片
 * @param bmp :点上的图片
 * @param drawMode 以点为中心,图片的绘制方式：
 *                 0:图片中心与点重叠；
 *                 1:图片垂直中心底部与点重叠；
 *                 2:图片左下角与点重叠
 *                 3:图片右下角与点重叠
 */
void MPoint::SetPointBmp(const CFbsBitmap* bmp ,int drawMode) 
	{
	if (drawMode < 0 || drawMode > 4)
	{
		User::Leave(KErrArgument);
	}
	
	//bmp为null时，给个默认图片
	SAFE_DELETE(mBmp);
	
	mBmp = bmp;
	mDrawMode = drawMode;
	if (NULL != mBmp)
	{
		bmpWidth = mBmp->SizeInPixels().iWidth;
		bmpHeight = mBmp->SizeInPixels().iHeight;
	}
	}

/**
 * 计算下一个缩放级别偏移量
 * @param zm   当前地图缩放级别
 * @param nzm  要计算的下一个缩放级别
 */
void MPoint::AdjustPointOffset(int zm,int nzm)
	{
   //搜索浏览过的记录点, 如果有则返回； 没有的话..就取当前缩放级别的点偏移量,并计算出下一个级别当前点的偏移量
   const TPoint* obj = mOffsetTable.Find(nzm);
   if (NULL != obj){
	   return ;
   }
   
   obj = mOffsetTable.Find(zm);//取当前级别点的偏移量
   if (NULL == obj){
	   return ;
   }
   
   const TPoint& zmOffset = *obj;

   //计算下一个缩放级别偏移量
   int nzmOffsetX = zmOffset.iX * Map::SCALE[zm] / Map::SCALE[nzm];
   int nzmOffsetY = zmOffset.iY * Map::SCALE[zm] / Map::SCALE[nzm];
   mOffsetTable.Insert(nzm, TPoint(nzmOffsetX,nzmOffsetY));
	}

void MPoint::DrawPoint(CGraphicsProxy& g)
{
	if (NULL != GetPointBmp())
	{ //在点上绘制设置的图片
		DrawBitmap(g);
	} else{
		//绘制2D的圆点
		DrawCircle(g);
	}
}

void MPoint::DrawBitmap(CGraphicsProxy& g)
{   
	int left = GetX();
	int top = GetY();
	rf.left = left;
	rf.top = top;
	rf.right = rf.left + GetWidth();
	rf.bottom = rf.top + GetHeight();
	g.DrawBitmap(TPoint(left, top), GetPointBmp());
}

void MPoint::DrawCircle(CGraphicsProxy& g)
{
	g.SetPenColor(KRgbBlue);
	int circle_wh = pSizes[map->GetZoom()];//圆的宽高
	int left = GetX();
	int top = GetY();
	rf.left = left;
	rf.top = top;
	rf.right = rf.left + circle_wh;
	rf.bottom = rf.top + pSizes[map->GetZoom()];
	
	// TODO: CGraphicsProxy::drawCircle
	g.drawCircle(left, top, circle_wh, p);
}
    
int MPoint::GetX() const
{
	x =(int) map->GetWidth()/2  + GetOffsetX(map->GetZoom()) - map->GetOriginDX();
	//0:图片中心与点重叠；
	//1:图片垂直中心底部与点重叠；
	//2:图片左下角与点重叠
	//3:图片右下角与点重叠
	switch(mDrawMode)
	{  
		case 0:
		case 1:
			x = x - GetWidth()/2;
			break;
		case 2:
			break;
		case 3:
			x = x - GetWidth();
			break;
	}
	return x;
}
    
int MPoint::GetY() const
{
	y = (int)map->GetHeight()/2 + GetOffsetY(map->GetZoom()) - map->GetOriginDY() ;
	//0:图片中心与点重叠；
	//1:图片垂直中心底部与点重叠；
	//2:图片左下角与点重叠
	//3:图片右下角与点重叠
	switch(mDrawMode)
	{  
		case 0:
			y = y - GetHeight()/2;
			break;
		case 1:
		case 2:
		case 3:
			y = y - GetHeight();
			break;
	}
	return y;
}

int MPoint::GetOffsetX(int zm) const 
{
	const TPoint* obj = mOffsetTable.Find(zm);//取当前级别点的偏移量
	if (NULL == obj)
		{
		return 0;
		}
	return obj->iX;
}
    

int MPoint::GetOffsetY(int zm) const 
{
	const TPoint* obj = mOffsetTable.Find(zm);//取当前级别点的偏移量
	if (NULL == obj)
		{
		return 0;
		}
	return obj->iY;
}
    
/**
 * 泡泡在点上的绘制方式(此函数只点上绘制泡泡使用)
 * @return: true: 泡泡以"点的图片"项部相对位置绘制；
 *          false:泡泡以"点的图片"中心相对位置绘制
 */
TBool MPoint::IsBubbleMode() const 
{
	return mode;
}

/**
 * 泡泡在点上的绘制方式(此函数只点上绘制泡泡使用)
 * @param mode true: 泡泡以"点的图片"项部相对位置绘制；
 *              false:泡泡以"点的图片"中心相对位置绘制
 */
void MPoint::SetBubbleMode(TBool mode) 
{
	this->mode = mode;
}

const CFbsBitmap* MPoint::GetPointBmp() const 
	{
    return mBmp;
    }
    
int MPoint::GetId() const 
	{
    return id;
    }

/**
 * 获取点(MPoint)在地图上绘制的区域
 * @return RectF
 */
const RectF& MPoint::GetRectF() const
{
	return rf;
}

void MPoint::SetId(int id) 
	{
    this->id = id;
    }
    
const TDesC& MPoint::GetLatlong() const
    {
	return latlong == NULL ? KNullDesC() : *latlong;
    }
    
void MPoint::SetLatlong(const TDesC& latlong)
    {
    SAFE_DELETE(this->latlong);
    this->latlong = latlong.Alloc();
    }
    
int MPoint::GetWidth() const
 	{
    return bmpWidth;
    }
    
int MPoint::GetHeight() const
	{
    return bmpHeight;
    }

double MPoint::GetLatitude() const 
	{
    return latitude;
    }

void MPoint::SetLatitude(double latitude) 
	{
    this->latitude = latitude;
    }

double MPoint::GetLongitude() const 
	{
	return longitude;
    }

void MPoint::SetLongitude(double longitude) 
	{
	this->longitude = longitude;
    }

const TDesC& MPoint::GetName() const 
	{
    return name == NULL ? KNullDesC() : *name;
    }

void MPoint::SetName(const TDesC& name) 
	{
	SAFE_DELETE(this->name);
	this->name = name.Alloc();
	}
    
TBool MPoint::IsClick(int x, int y) const
    {   
	//扩大点的单击区域
	RectF rf;
	rf.left = GetRectF().left - 3;
	rf.top = GetRectF().top - 3;
	rf.right = GetRectF().right + 3;
	rf.bottom = GetRectF().bottom + 3;
	if (rf.Contains(x, y))
	{
		return true;
	}
	return false;
    }
